home *** CD-ROM | disk | FTP | other *** search
/ MacUser Mac Bin 25 / MACUSER-MACBIN25-1995-12.ISO.7z / MACUSER-MACBIN25-1995-12.ISO / 本誌連動 / HyperCard office.9512⁄CD / 95-07 < prev    next >
Text File  |  1995-10-01  |  16KB  |  317 lines

  1. テキスト、テキスト、テキスト!
  2.  
  3.  オフィスの情報の多くは文書、すなわちテキスト情報である。このデータをいかにうまく処理するかが、効率的なオフィスシステムを構築するときのキーポイントになる。
  4.  
  5. --
  6. 前回の復習
  7.  
  8. 前回はハイパーカードがオフィス処理を行うに当たって強力なツールになりうることを示した。その理由として
  9.  1)優れたテキスト処理能力
  10.  2)自動操作と高度なカスタマイズ
  11.  3)バンドルされる無料ソフト
  12. の3つを挙げ、第2のポイントの具体例としてドキュメントローンチャと簡易電子掲示板を作成した。今回は、第1のポイント、テキスト処理に的を絞ってオフィスシステムの構築を考えてみることにしたい。
  13.  
  14. --
  15. なぜテキスト形式にこだわるのか
  16.  
  17.  前回も述べたように、オフィスで扱う情報の大半は文書、すなわちテキストである。材料となるデータを探してきて、それを説得力のある報告書や企画書にまとめる。日常の仕事にはこういう作業が多いのではないだろうか。
  18.  最終的な完成品には見栄えの良さが必要だとしても、データの蓄積や加工の段階では、レイアウトなどの余計な情報を付加しない、純粋なテキストのほうが扱いやすい( _*注1_ )。例えばデータを特定のファイル形式にすると専用のアプリケーションでしか扱えなくなってしまうが、テキスト形式ならどんなソフトでも直接利用できる。
  19.  特定形式で保存された情報は、いわば調理済みのお惣菜のようなものだ。データは加工し組合せることで新しい価値を生み出す。その素材はできるだけ生のままで、調理しやすい形にしておくべきなのである。
  20.  
  21. --
  22. 情報の寿命
  23.  
  24.  これとは別に、テキストにこだわるもう一つの大きな理由がある。情報の寿命とでもいうようなことだ。
  25.  わずか十数年のパーソナルコンピュータの歴史でも、いろいろな機種の栄枯盛衰があった。今のところマッキントッシュとウインドウズの2つが主流となっているが、この先もこれらが広く使われるという保証はない。実際、日本のオフィスに急速に普及した専用ワープロは、今コンピュータに席を譲ろうとしているが、それに際してこれまでの文書資産をどうやって引き継ぐかが問題になっている。専用ワープロは各社が独自のフォーマットにこだわったため、データの互換性に大きな障害を残してしまったのだ。
  26.  オフィスの情報は、何十年という単位で活用されるべきものである。これを時の流行りに合わせて特定の機種と心中させるわけにはいかない。この点で、最も汎用性がある情報記録形態が「テキスト」ファイル形式なのである( _*注2_ )。細かいことは別にして、これならば他のコンピュータ上でも再利用可能だ。
  27.  大切なのは機械ではなく情報自身である。財産を汎用性のあるテキスト形式にしておくことは“転ばぬ先の杖”と言ってよい。
  28.  
  29. --
  30. ハイパーカードのテキスト処理
  31.  
  32.  ハイパートークではcharacter, word, item, lineなどの識別子でテキストの要素を指定し、put命令で前や後ろに繋ぐというような文字列操作ができる。たとえば
  33.     put "Taro loves Hanako" into S1
  34.     delete last character of word 2 of S1
  35.     put "Does " before S1
  36.     put "?" after S1
  37. とすると、S1の中身は"Does Taro love Hanako?"という疑問文に変換されるわけだ。さらに _offset_ 関数や _contains_ 演算子を使えば一つの文中に特定の言葉が含まれるかどうかを調べられるし、 _sort_ 命令を使えば一定規則により文を並べ替えることもできる。ハイパーカードの内部では数字も文字列として処理されるので、数字と文字が入り交じったデータの処理も簡単である。
  38.  豊富な命令をここで全て紹介するわけには行かないが、ハイパートークのテキスト処理は強力で柔軟である。こうした機能を組み合わせることで、素材となる文を自由に加工し、新しい情報として付加価値を与えることが可能になる。
  39.  
  40. --
  41. 簡単なデータベースへの応用
  42.  
  43.  ハイパーカードの機能を使って、簡単なテキストデータベースを作ってみよう。ハイパーカードはカード1枚に一つのレコードを納めて、カード型データベースのように使うことが多いが(付録で付いてくる住所録などがそうだ)、ここではテキストファイルにこだわって、データ自身はスタックとは別のファイルに持つことにする。
  44.  一般に、データの入れ物とデータ自身を独立させておくのは賢明な手法である。こうすることでデータの加工が容易になるだけでなく、将来システムを見直すことがあってもデータは無傷で残すことができるし、そのまま他の機種に持っていくことも可能だからだ。
  45.  ここで作成するのは、カードの左上では常にタイトルの一覧が表示されていて、必要なタイトルをクリックするとその内容が下部に表示されるという形を取る(図1)。データベースのリスト表示と個別表示を同時に使う感覚だ。
  46.  
  47. --
  48. データファイルの作成
  49.  
  50.  まず、素材となるデータを用意する。データの要素はタイトル(1行)と内容の2つのみ。たとえば、この原稿を1つのデータベースとすると、小見出しを「タイトル」、それに続く本文を「内容」と考えることができる。データ中の個々のレコードを区別するために、内容と次のタイトルを半角ハイフン2つ(--)だけの行で区切ることにする( _*注3_ )。つまり
  51.     タイトル1
  52.     内容1
  53.     ・・・
  54.     内容1の終わり
  55.     --
  56.     タイトル2
  57.     内容2
  58.     ・・・
  59.     内容2の終わり
  60.     --
  61. という具合になる。素材は何でも構わない。毎日の営業日誌でも良いし、いろいろなアイデアのメモでも良い。手元に転がっている雑多なデータを、気楽に--で区切ったテキストファイルにしてみよう。
  62.  
  63. --
  64. タイトルの抽出
  65.  
  66.  データができたら、ここからタイトルを抽出して見出し一覧を作成する。 _リスト1_ に示したように、ファイルを読み込んで( _*注4_ )1行ずつデータを検証し、区切り行(--)が現れたら次の行はタイトル、その次の行からは内容とみなして処理していく。ポイントは、区切り行の位置をインデックスとして記録するところである。一覧表でタイトルが選ばれたら、このインデックスを頼りにファイルから内容を読み出す。
  67.  ここでインデックスの最初が0になる(on updateDataの5行目)ことに注意。データファイルの先頭には区切り行は置かないが、先頭行の前(つまり0行目)に仮想的に区切り行を設定して、読み出し処理を簡単にしているのである。
  68.  
  69. --
  70. 内容の表示
  71.  
  72.  タイトル一覧を表示しているフィールドは「 _ロックテキスト_ 」をチェックし、マウスのクリックを受け付けるようにしておく。フィールドのスクリプトは _リスト2_ のように簡単なものだ。クリックされた行を調べ(word 2 of _the clickLine_ )、インデックスフィールドからそれに対応する区切り行(--)の位置を取得し、ファイルから内容を読み出して表示する。
  73.  
  74. --
  75. 検索機能を加える
  76.  
  77.  データベースと名乗るからには検索機能も用意したい。ハイパートーク命令だけでは高速検索は難しいが、いろいろ応用の利くスクリプトなので検討してみよう( _リスト3_ )。
  78.  データファイルを読み込んで、検索語句が含まれるかどうかをcontains演算子で順番に調べていく。全文検索をすると同一レコードで複数ヒットする場合があるので、結果リストを作る前にこのチェックをしておかなければならない。
  79.  検索結果は、タイトルとそれが一覧中の何番目に当たるかを示す行番号をセットにして返す(図1の右上のフィールド)。スピード優先なら、全文検索を諦め、登録されたタイトルに検索語句があるかどうか調べることで我慢するという手もある。
  80.  結果リストフィールドでは、この行番号を頼りにインデックスを調べ、内容を表示するようにした( _リスト4_ )。基本的には前節の内容表示スクリプトと同じである。
  81.  
  82. --
  83. 電子掲示板との連動
  84.  
  85.  さて、これだけの機能なら専用データベースソフトを使ったほうが高速なものができるわけで、このままではハイパーカードを使う必然性はあまりない。しかし、これを前回作った電子掲示板と組み合わせるとなかなか面白い使い方ができる。
  86.  前回の掲示板は日付をファイル名にすることで表示すべき情報を識別していた( _95-06:電子掲示板_ )。しかしこれでは、指定の日に出張していた人には情報を伝えることができないし、情報をさかのぼって調べることも難しい。そこで、メッセージをテキストデータベースの形で蓄積し、新しい情報が追加されたときに掲示板を自動表示するようにしておけば(図2)、確実にメッセージを伝達でき、古い情報も有効に活用することが可能になるはずだ(図3)。
  87.  データベースの側面から見れば、単に情報を蓄積するだけでなく、新規情報を直ちにメンバーに知らせられる点がユニークと言える。受け身のデータベースが、ユーザーへ積極的に情報提供するダイナミックなものに変身するわけだ。
  88.  
  89. --
  90. 掲示板データベースの作成
  91.  
  92.  この掲示板データベースを作るには、前に述べた区切り行付きテキストファイルの形式で新しいメッセージをファイルの先頭に順次追加していくだけでよい。ファイルを保存したらタイトル抽出を行う。前と違うのは、抽出したタイトル一覧とインデックスを、フィールドでなくファイルに保存するところである。スタックの起動プロセスの中で毎回このファイルをチェックし、トップに来るタイトルがまだ読んだことのないものであれば新規メッセージが送られたものとみなして、スタックのフィールドを更新し、メッセージの内容を表示するという仕掛けだ( _リスト5_ )。
  93.  
  94. --
  95. テキストデータの応用
  96.  
  97.  データベースほど手間をかけなくてもテキストデータを活用する方法はある。
  98.  例えば、共有ファイルのフォルダを作っているようなケース。少数のファイルならともかく、100にも及ぶファイルから必要なものを見つけるのは簡単ではない。ここに今回の手法を応用してみよう。
  99.  ファイルを保存するとき、それぞれ内容を説明する<文書タイトル>を、先のデータベースの“タイトル一覧フィールド”に登録するようにしておく。“インデックスフィールド”には行番号の代わりにファイル名を登録する。こうすれば、文書タイトルに基づいて簡単に必要なファイルを検索・表示する仕組みができあがるというわけだ。この簡易ファイル登録システムは、ファイル名よりも詳しい説明が付加できるうえに、いちいちワープロソフトを立ち上げなくてもテキストを参照することができる( _*注5_ )ので、思いのほか便利である。
  100.      * * *
  101.  ハイパーカードの命令だけでもこれだけの機能を実現できるが、外部命令を使えばもっとスマートに高速にデータを処理することが可能だ。タイトルの一覧をダイアログボックスで表示したり、フォルダ内の全テキストファイルに対して一括全文検索をかけるということもさほど難しくない。こうした外部命令については、また回を改めて紹介していく予定である。
  102.  
  103. --
  104. *注1
  105.  
  106. テキスト形式で文書を作成するのには、エディタと呼ばれるソフトを使うのが便利である。これらの多くはフリーソフトとして入手できるのでなお都合がよい。ワープロを使う場合は、保存文書のファイルタイプが「TEXT」のものだと、文字部分は直接ハイパーカードからも参照できるので、いろいろな応用が可能である。
  107.  
  108. --
  109. *注2
  110.  
  111. エクセルのように複数機種で使える有力なファイル形式もあるが、テキストほどの汎用性はないし、これらがこの先何十年も主流であるとは限らない。
  112.  
  113. --
  114. *注3
  115.  
  116. 区切りはどのようにしても良いのだが、こうしておくとフリーウェアのEasy Viewでデータを直接リスト表示することができる。繰り返すが、テキストファイルはこのようにいろいろなアプリケーションから縦横に活用できるのである。
  117.  
  118. --
  119. *注4
  120.  
  121. データ読み込みの命令は頻繁に利用するので、 _リスト1_ のようにReadFile()という関数を作ってスタックスクリプトに置いておく。こうしておくと、エラー処理、統計など将来ファイルまわりの命令を追加するときもここを修正するだけで良い。
  122.  
  123. --
  124. *注5
  125.  
  126. ファイルタイプが「TEXT」になるワープロやエディタを使っていないと、ハイパーカード上で内容を閲覧するのは難しくなる。こういう点を見ても、テキスト形式のメリットが理解できるだろう。
  127.  
  128. --
  129. リスト1
  130.  
  131. on mouseUp
  132.   answer file "データファイル" of type TEXT
  133.   if it is "" then exit mouseUp
  134.   updateData it
  135. end mouseUp
  136.  
  137. on updateData FileName
  138.   set cursor to watch
  139.   put ReadFile(FileName) into str -- ファイル読み込み
  140.   put "" into titles
  141.   put "0" & RETURN into Indexs -- 0行目を仮想的に区切り行扱いする
  142.   put "--" into separator
  143.   put TRUE into header -- タイトルかどうかを判定
  144.   
  145.   repeat with i=1 to number of lines of str
  146.     set cursor to busy
  147.     if header is TRUE then
  148.       put line i of str & RETURN after titles
  149.       put FALSE into header
  150.     else if line i of str is separator then
  151.       --区切り行なら行番号をインデックスに加え、次の行がタイトルであることを示す
  152.       put i & RETURN after Indexs
  153.       put TRUE into header
  154.     end if
  155.   end repeat
  156.   
  157.   put titles into fld "Title"
  158.   put Indexs into fld "Index"
  159.   put lastHCItem(":", FileName) into line 1 of fld "FileInfo"
  160.   put FileName into line 2 of fld "FileInfo"
  161. end updateData
  162.  
  163. function ReadFile FileName
  164.   open file FileName
  165.   read from file FileName until EOF
  166.   close file FileName
  167.   return it
  168. end ReadFile
  169.  
  170. --
  171. リスト2
  172.  
  173. on mouseUp
  174.   showData (word 2 of the clickLine) -- クリックした行
  175. end mouseUp
  176.  
  177. on showData LineNo
  178.   put line lineNo to LineNo+1 of fld "Index" into POS
  179.   -- Indexの対応する行が前のレコードとの区切り、
  180.   -- 次のIndexが次のレコードとの区切り行を示している
  181.   
  182.   put ReadFile(line 2 of fld "FileInfo") into str
  183.   put line (line 1 of POS +1) to (line 2 of POS -1) of str into fld "TEXT"
  184.   -- line (line 1 of POS) to (line 2 of POS) of strとすると区切り行も含まれる
  185.   
  186.   show fld "TEXT"
  187. end showData
  188.  
  189. --
  190. リスト3
  191.  
  192. on mouseUp
  193.   ask "検索語句?" with fld "SearchWord"
  194.   if it is "" then exit mouseUp
  195.   put it into SearchWord
  196.   put ReadFile(line 2 of fld "FileInfo") into str
  197.   put "" into res
  198.   
  199.   -- SearchWordを含むかどうか1行ずつ調べる
  200.   repeat with i=1 to number of lines of str
  201.     set cursor to busy
  202.     if line i of str contains SearchWord then
  203.       put i & RETURN after res
  204.     end if
  205.   end repeat
  206.   
  207.   if res is "" then
  208.     answer "「" & SearchWord & "」は見つかりませんでした。"
  209.     exit mouseUp
  210.   end if
  211.   
  212.   -- 同一レコードでヒットしたものをまとめる
  213.   put fld "Index" into Indexs
  214.   put fld "Title" into titles
  215.   put 1 into currentPos
  216.   put number of lines of Indexs into n
  217.   set numberFormat to "000"
  218.   
  219.   -- SearchWordが含まれる行番号について
  220.   repeat with i=1 to number of lines of res
  221.     repeat with k=currentPos to n
  222.       if line i of res < line k of Indexs then
  223.         -- インデックスの行番号が検索結果の行番号より大きければ、この結果は
  224.         -- 一つ前のレコードに含まれることになる
  225.         
  226.         if k is currentPos then exit repeat -- 同一レコードのヒットは省略
  227.         put k into currentPos
  228.         
  229.         -- タイトルの前に一覧中の何番目に当たるかを示す行番号を付加する
  230.         put k-1 && ":" &&line k-1 of titles & RETURN after foundSec
  231.         
  232.         exit repeat
  233.       end if
  234.     end repeat
  235.   end repeat
  236.   
  237.   put foundSec into fld "List"
  238.   show fld "List"
  239. end mouseUp
  240.  
  241. --
  242. リスト4
  243.  
  244. on mouseUp
  245.   put word 2 of the clickLine into thisLine -- 検索結果でクリックした行
  246.   
  247.   -- タイトル一覧での行番号を _リスト2_ のshowDataに送る
  248.   showData (word 1 of line thisLine of me)
  249. end mouseUp
  250.  
  251. --
  252. リスト5
  253.  
  254. on startUp
  255.   --
  256.   put <message title file> into msgTitle -- 抽出したタイトルを保存するファイル
  257.   if there is a file msgTitle then
  258.     put ReadFile(msgTitle) into Titles
  259.     put "MsgBoard" into cdName
  260.     
  261.     -- タイトルの1行目を前回表示したメッセージのタイトルと比較し、
  262.     -- 新しいタイトルが保存されていればカードを更新する
  263.     if cd fld "LastMsg" is NOT line 1 of Titles then
  264.       go cd cdName
  265.       updateData <message file> -- _リスト1_ と同様にしてデータの更新
  266.       put line 1 of Titles into cd fld "LastMsg"
  267.       showData 1 -- _リスト2_ のshowDataに最初のレコードを読むよう依頼する
  268.     end if
  269.   end if
  270.   --
  271. end startUp
  272.  
  273. --
  274. offset
  275.  
  276. ある文字列S1が別の文字列S2の何文字目に含むまれるか(もしくは含まれないか)調べます。
  277.     put "Mac" into S1
  278.     put "This magazine is MacUser Japan" into S2
  279.     put offset(S1, S2) into pos
  280. とすると、変数posには18という結果が代入されます。S2(の先頭)はS1の18文字目にあることが分かります。
  281. 日本語の扱いはHC2.1とHC2.2の間で変更されているので注意が必要です。HC2.1ではoffsetが返す値はバイトポジション(全角1文字が2バイト)であったのに対し、HC2.2ではcharつまり何文字目かという値になっています。
  282.  
  283. --
  284. contains
  285.  
  286. ある文字列S1が別の文字列S2を含むかどうか調べます。
  287.     put "This magazine is MacUser Japan" into S1
  288.     put "Mac" into S2
  289.     if S1 contains S2 then ...
  290. のように使います。
  291. よく似ていますが、S1とS2の関係が逆となるものにis in演算子があります。上の例で言えば3行目が
  292.     if S2 is in S1 then ...
  293. という形になります。
  294. いずれも結果はTRUE/FALSEで返されます。
  295.  
  296. --
  297. sort
  298.  
  299. 表計算のワークシートから書き出したような行単位のデータを扱うとき、この命令で並べ替えを行う。例えば、データstrが氏名,身長,体重の順でitemとして区切られているとき、
  300.     sort str descending numeric by item 2 of each
  301. とすると、データを身長の高い順に(降順に)並べ替えることができる。
  302.  
  303. --
  304. ロックテキスト
  305.  
  306. フィールドの属性の一つで、これがFALSEならばフィールドのテキストを編集できる。逆にTRUEになっていると、そのフィールドは編集できない代わりにマウスのクリックを受け付けるようになる。フィールドスクリプトにmouseUpなどのハンドラを処理させるにはテキストをロックしておく必要がある。
  307.  
  308. --
  309. the clickLine
  310.  
  311. ロックテキストされたフィールドをクリックしたとき、この関数を使うと何行目をクリックしたかを調べることができる。例えば、フィールドの3行目をクリックすると、the clickLineの結果は
  312.     line 3 of bkgnd field 1
  313. のようになる。従って、行番号を得たいときは
  314.     word 2 of the clickLine
  315. とすればよい。
  316. --
  317.